(import (fibers)
        (fibers channels)
        (ice-9 match)
        ;; structs
        (srfi srfi-9)
        ;; for functional structs (not part of srfi-9 directly)
        (srfi srfi-9 gnu))

(define-immutable-record-type <point>
  (make-point x y)
  point?
  (x point-x set-point-x)
  (y point-y set-point-y))


(set-record-type-printer!
 <point>
 (λ (record port)
   (simple-format port
                  "<point: x: ~a, y: ~a>\n"
                  (point-x record)
                  (point-y record))))


(define server
  (λ (in out)
    ;; infinite blocking loop
    (let lp ()
      (match (pk 'server-received #|block on get-message|# (get-message in))
        ('ping! (put-message out 'pong!))
        ('sup   (put-message out 'not-much-u))
        (msg    (put-message out (cons 'wat msg))))
      (lp))))

(define client
  (λ (in out)
    (for-each (λ (msg)
                (put-message out msg)
                (pk 'client-received (get-message in)))
              (list '(1 2 3)
                    #(1 2 3)
                    ;; We can pass non-string data between fibers!
                    (make-point 1 2)))))

(run-fibers (λ ()
              (let ((c2s (make-channel))
                    (s2c (make-channel)))
                (spawn-fiber (λ () (server c2s s2c)))
                (client s2c c2s))))
